package org.dromara.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.dromara.admin.domain.ContractBill;
import org.dromara.admin.domain.GeneralConfig;
import org.dromara.admin.domain.UserDetail;
import org.dromara.admin.domain.bo.ContractBillBo;
import org.dromara.admin.domain.vo.ContractBillVo;
import org.dromara.admin.domain.vo.UserDetailVo;
import org.dromara.admin.enums.*;
import org.dromara.admin.service.IAdvanceBillService;
import org.dromara.admin.service.IContractBillService;
import org.dromara.admin.service.IUserDetailService;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.lessor.domain.House;
import org.dromara.lessor.domain.bo.HouseBo;
import org.dromara.lessor.domain.vo.HouseVo;
import org.dromara.system.domain.SysUser;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.dromara.admin.domain.bo.OrderBo;
import org.dromara.admin.domain.vo.OrderVo;
import org.dromara.admin.domain.Order;
import org.dromara.admin.mapper.OrderMapper;
import org.dromara.admin.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author Lion Li
 * @date 2025-09-03
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OrderServiceImpl implements IOrderService {

    private final OrderMapper baseMapper;
    private final IContractBillService contractBillService;
    private final IAdvanceBillService advanceBillService;
    private final IUserDetailService userDetailService;

    /**
     * 查询订单
     *
     * @param id 主键
     * @return 订单
     */
    @Override
    public OrderVo queryById(Long id) {
        MPJLambdaWrapper<Order> wrapper = getOrderInfoByJoinTable();
        wrapper.eq(Order::getId, id);
        OrderVo orderVo = baseMapper.selectJoinOne(OrderVo.class, wrapper);
        if (BeanUtil.isEmpty(orderVo)) {
            throw new ServiceException("订单信息不存在！");
        }
        return orderVo;
    }

    /**
     * 租户查询订单详情
     *
     * @param id
     * @return
     */
    @Override
    public OrderVo tenantGetOrderInfo(Long id) {
        return queryById(id);
    }

    /**
     * 获取订单详情联表查询
     */
    private static MPJLambdaWrapper<Order> getOrderInfoByJoinTable() {
        // 使用MPJBaseMapper进行联表查询order表、House、GeneralConfig、ContractBill、SysUser表
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<Order>()
            .selectAll(Order.class) // 订单表字段
            .selectCollection(ContractBill.class, OrderVo::getContractBills)
            .selectAssociation(House.class, OrderVo::getHouse)
            .selectAssociation(GeneralConfig.class, OrderVo::getGeneralConfig)
            .selectAssociation("tu", SysUser.class, OrderVo::getTenantUser)
            .selectAssociation("lu", SysUser.class, OrderVo::getLessorUser)
            .selectAssociation("cu", SysUser.class, OrderVo::getCapitalUser)
            .leftJoin(House.class, House::getId, Order::getHouseId)
            .leftJoin(GeneralConfig.class, GeneralConfig::getId, House::getHouseLayoutId)
            .leftJoin(ContractBill.class, ContractBill::getOrderId, Order::getId)
            // 租客信息 join
            .leftJoin(SysUser.class, "tu", on -> on.eq(SysUser::getUserId, Order::getUserId))
            // 出租方信息 join
            .leftJoin(SysUser.class, "lu", on -> on.eq(SysUser::getUserId, Order::getLessorUserId))
            // 资方代理信息 join
            .leftJoin(SysUser.class, "cu", on -> on.eq(SysUser::getUserId, Order::getCapitalUserId));
        return wrapper;
    }

    /**
     * 分页查询订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 订单分页列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TableDataInfo<OrderVo> queryPageList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo);
        wrapper.eq(StringUtils.isNotBlank(bo.getAdvanceBillStatus()), Order::getAdvanceBillStatus, bo.getAdvanceBillStatus())
            .eq(StringUtils.isNotBlank(bo.getRentBillStatus()), Order::getRentBillStatus, bo.getRentBillStatus());
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);

        // 遍历查询订单里面的账单信息是否有到期未付款，并且billType为RENT
        page.getRecords().forEach(orderVo -> {
            if (CollUtil.isNotEmpty(orderVo.getContractBills())) {
                orderVo.getContractBills().forEach(contractBill -> {
                    if (contractBill.getBillType().equals(BillType.RENT.getCode())
                        && contractBill.getOverdue().equals(AuditStatus.N.getCode())) {
                        if (contractBill.getBillStatus().equals(BillStatus.UNPAID.getCode())
                            || contractBill.getBillStatus().equals(BillStatus.PART.getCode())) {
                            if (DateUtil.compare(contractBill.getExpiresTime(), DateUtil.date()) < 0) {
                                contractBill.setOverdue(AuditStatus.Y.getCode());
                                contractBillService.updateByBo(BeanUtil.copyProperties(contractBill, ContractBillBo.class));
                                log.info("订单{}账单{}到期未付款", orderVo.getId(), contractBill.getId());
                                if (!orderVo.getRentBillStatus().equals(BillStatus.OVERDUE.getCode())) {
                                    orderVo.setRentBillStatus(BillStatus.OVERDUE.getCode());
                                    this.updateByBo(BeanUtil.copyProperties(orderVo, OrderBo.class));
                                }
                            }
                        }
                    }
                });
            }
        });
        return TableDataInfo.build(page);
    }

    /**
     * 分页查询今日付租订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageTodayList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo);
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        DateTime begin = DateUtil.beginOfDay(DateUtil.date());
        DateTime end = DateUtil.endOfDay(DateUtil.date());
        return getOrderVoTableDataInfo(page, begin, end);
    }

    /**
     * 处理order里面账单数据
     */
    @NotNull
    private TableDataInfo<OrderVo> getOrderVoTableDataInfo(Page<OrderVo> page, DateTime begin, DateTime end) {
        // 提取 orderIds
        List<Long> orderIds = page.getRecords().stream().map(OrderVo::getId).collect(Collectors.toList());
        // 查询在时间范围内到期的账单
        List<ContractBillVo> todayBills = contractBillService.selectListByOrderIds(orderIds, begin, end);
        if (CollUtil.isEmpty(todayBills)) {
            // 没有任何账单，直接返回空
            page.setRecords(Collections.emptyList());
            page.setTotal(0);
            return TableDataInfo.build(page);
        }
        // 按 orderId 分组
        Map<Long, List<ContractBillVo>> billMap = todayBills.stream().collect(Collectors.groupingBy(ContractBillVo::getOrderId));
        // 组装结果

        // 6. 过滤掉没有账单的 order
        List<OrderVo> filteredOrders = page.getRecords().stream()
            .filter(orderVo -> billMap.containsKey(orderVo.getId()))
            .peek(orderVo -> orderVo.setContractBills(billMap.get(orderVo.getId())))
            .toList();
        page.setRecords(filteredOrders);
        page.setTotal(filteredOrders.size());
        return TableDataInfo.build(page);
    }

    /**
     * 分页查询明日付租订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageTomorrowList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo);
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        DateTime begin = DateUtil.beginOfDay(DateUtil.tomorrow());
        DateTime end = DateUtil.endOfDay(DateUtil.tomorrow());
        return getOrderVoTableDataInfo(page, begin, end);
    }

    /**
     * 分页查询未来五天付租订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageFiveDaysList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo);
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        DateTime begin = DateUtil.beginOfDay(DateUtil.date());
        DateTime end = DateUtil.endOfDay(DateUtil.offsetDay(DateUtil.date(), 30));
        return getOrderVoTableDataInfo(page, begin, end);
    }

    /**
     * 分页查询逾期付租订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageOverdueList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo);
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        return getOrderVoTableDataInfo(page, null, null);
    }

    /**
     * 联表查询order表、House、GeneralConfig、ContractBill、SysUser表
     */
    private static MPJLambdaWrapper<Order> getOrderListByJoinTable(OrderBo bo) {
        // 使用MPJBaseMapper进行联表查询order表、House、GeneralConfig、ContractBill、SysUser表
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<Order>()
            .selectAll(Order.class) // 订单表字段
            .selectAssociation(House.class, OrderVo::getHouse)
            .selectAssociation(GeneralConfig.class, OrderVo::getGeneralConfig)
            .selectAssociation("tu", SysUser.class, OrderVo::getTenantUser)
            .selectAssociation("lu", SysUser.class, OrderVo::getLessorUser)
            .selectAssociation("cu", SysUser.class, OrderVo::getCapitalUser)
            .leftJoin(House.class, House::getId, Order::getHouseId)
            .leftJoin(GeneralConfig.class, GeneralConfig::getId, House::getHouseLayoutId)
            // 租客信息 join
            .leftJoin(SysUser.class, "tu", on -> on.eq(SysUser::getUserId, Order::getUserId))
            // 出租方信息 join
            .leftJoin(SysUser.class, "lu", on -> on.eq(SysUser::getUserId, Order::getLessorUserId))
            // 资方代理信息 join
            .leftJoin(SysUser.class, "cu", on -> on.eq(SysUser::getUserId, Order::getCapitalUserId))
            .like(StrUtil.isNotBlank(bo.getUserName()), "tu.user_name", bo.getUserName())
            .like(StrUtil.isNotBlank(bo.getLessorUserName()), "lu.user_name", bo.getLessorUserName())
            .like(StrUtil.isNotBlank(bo.getCapitalUserName()), "cu.user_name", bo.getCapitalUserName())
            .eq(StrUtil.isNotBlank(bo.getOrderStatus()), Order::getOrderStatus, bo.getOrderStatus())
            .eq(StrUtil.isNotBlank(bo.getCapitalAuditStatus()), Order::getCapitalAuditStatus, bo.getCapitalAuditStatus());
        return wrapper;
    }

    /**
     * 分页查询当前登录用户的订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryMyPageList(OrderBo bo, PageQuery pageQuery) {
        // 使用MPJBaseMapper进行联表查询order表、house表、contract_bill表，根据用户ID查询所有订单
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<Order>()
            .selectAll(Order.class)//查询order表全部字段
            .selectAssociation(House.class, OrderVo::getHouse)
            .leftJoin(House.class, House::getId, Order::getHouseId)
            .eq(Order::getUserId, bo.getUserId())
            .eq(StrUtil.isNotBlank(bo.getOrderStatus()), Order::getOrderStatus, bo.getOrderStatus())
            .eq(StrUtil.isNotBlank(bo.getRentBillStatus()), Order::getRentBillStatus, bo.getRentBillStatus());
        List<OrderVo> houseVoList = baseMapper.selectJoinList(OrderVo.class, wrapper);
        return TableDataInfo.build(houseVoList);
    }

    /**
     * 分页查询当前资方用户的订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @param userId    用户id
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageMyCapitalOrderList(OrderBo bo, PageQuery pageQuery, Long userId) {
        bo.setCapitalUserId(userId);
        // 获取当前用户的折扣比例
        UserDetailVo userDetailVo = userDetailService.queryById(userId);
        Long discountRate = userDetailVo.getDiscountRate(); // 折扣比例90
        if (discountRate == null) {
            throw new ServiceException("未设置资方折扣比例！");
        }
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo).eq(Order::getCapitalUserId, userId);
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        page.getRecords().forEach(orderVo -> {
            orderVo.setCapitalAdvanceAmount(orderVo.getRentTotal().multiply(new BigDecimal(discountRate)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
        });
        return TableDataInfo.build(page);
    }

    /**
     * 分页查询当前房东的订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return
     */
    @Override
    public TableDataInfo<OrderVo> queryPageMyLessorOrderList(OrderBo bo, PageQuery pageQuery) {
        MPJLambdaWrapper<Order> wrapper = getOrderListByJoinTable(bo).eq(Order::getLessorUserId, bo.getLessorUserId());
        Page<OrderVo> page = baseMapper.selectJoinPage(pageQuery.build(), OrderVo.class, wrapper);
        return TableDataInfo.build(page);
    }

    /**
     * 查询符合条件的订单列表
     *
     * @param bo 查询条件
     * @return 订单列表
     */
    @Override
    public List<OrderVo> queryList(OrderBo bo) {
        LambdaQueryWrapper<Order> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Order> buildQueryWrapper(OrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Order> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(Order::getId);
        lqw.eq(StringUtils.isNotBlank(bo.getContractNo()), Order::getContractNo, bo.getContractNo());
        lqw.eq(bo.getStartDate() != null, Order::getStartDate, bo.getStartDate());
        lqw.eq(bo.getEndDate() != null, Order::getEndDate, bo.getEndDate());
        lqw.eq(bo.getContractMonth() != null, Order::getContractMonth, bo.getContractMonth());
        lqw.eq(bo.getRent() != null, Order::getRent, bo.getRent());
        lqw.eq(bo.getDeposit() != null, Order::getDeposit, bo.getDeposit());
        lqw.eq(bo.getRentTotal() != null, Order::getRentTotal, bo.getRentTotal());
        lqw.eq(bo.getHouseId() != null, Order::getHouseId, bo.getHouseId());
        lqw.eq(bo.getUserId() != null, Order::getUserId, bo.getUserId());
        lqw.eq(bo.getLessorUserId() != null, Order::getLessorUserId, bo.getLessorUserId());
        lqw.eq(bo.getCapitalUserId() != null, Order::getCapitalUserId, bo.getCapitalUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), Order::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), Order::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getSigningStatus()), Order::getSigningStatus, bo.getSigningStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPlatformAuditStatus()), Order::getPlatformAuditStatus, bo.getPlatformAuditStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getCapitalAuditStatus()), Order::getCapitalAuditStatus, bo.getCapitalAuditStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPledgeStatus()), Order::getPledgeStatus, bo.getPledgeStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getRentBillStatus()), Order::getRentBillStatus, bo.getRentBillStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getAdvanceBillStatus()), Order::getAdvanceBillStatus, bo.getAdvanceBillStatus());
        lqw.eq(bo.getSigningTime() != null, Order::getSigningTime, bo.getSigningTime());
        lqw.eq(bo.getAuditTime() != null, Order::getAuditTime, bo.getAuditTime());
        return lqw;
    }

    /**
     * 新增订单
     *
     * @param bo 订单
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OrderBo bo) {
        Order add = MapstructUtils.convert(bo, Order.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改订单
     *
     * @param bo 订单
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(OrderBo bo) {
        Order update = MapstructUtils.convert(bo, Order.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 资方审核是否愿意接单
     *
     * @param bo        订单
     * @param capitalId 资方id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean capitalAudit(OrderBo bo, Long capitalId) {
        Order order = baseMapper.selectById(bo.getId());
        if (BeanUtil.isEmpty(order)) {
            throw new ServiceException("订单信息不存在！");
        }
        if (!order.getPlatformAuditStatus().equals(AuditStatus.APPROVED.getCode()) &&
            !order.getPlatformAuditStatus().equals(AuditStatus.REJECTED_REASSIGN.getCode())) {
            throw new ServiceException("订单状态异常或平台未通过！");
        }
        // 判断订单是否已指派资方
        if (order.getCapitalUserId() == null) {
            throw new ServiceException("本订单还未指派资方！");
        }
        // 判断这条订单是否指派本人的
        if (!capitalId.equals(order.getCapitalUserId())) {
            throw new ServiceException("非指派本人不可操作！");
        }
        // 判断这条订单是否已经有资方审核过
        if (AuditStatus.APPROVED.getCode().equals(order.getCapitalAuditStatus())) {
            throw new ServiceException("订单已经资方审核过了！");
        }

        // 根据资方审核状态进行判断
        // 拒绝
        if (AuditStatus.REJECTED.getCode().equals(bo.getCapitalAuditStatus())) {
            bo.setPlatformAuditStatus(AuditStatus.REJECTED_REASSIGN.getCode());
            return baseMapper.updateById(MapstructUtils.convert(bo, Order.class)) > 0;
        }
        // 通过
        if (AuditStatus.APPROVED.getCode().equals(bo.getCapitalAuditStatus())) {
            // 添加租客账单中资方id -> 在账单表中根据orderId查询列表赋值资方id
            Boolean b = contractBillService.updateCapitalIdByOrderId(order);
            if (!b) {
                throw new ServiceException("更新租客账单中资方id失败！");
            }
            // 创建资方账单
            advanceBillService.createAdvanceBill(order);
            // 更新订单审核状态
//            order.setOrderStatus(OrderStatus.EFFECTING.getCode());
//            order.setSigningStatus(SigningStatus.SIGNING.getCode());
            order.setAdvanceBillStatus(BillStatus.PENDING_PAY.getCode()); // 垫资分期账单状态
            order.setCapitalAuditStatus(bo.getCapitalAuditStatus());
            return baseMapper.updateById(order) > 0;
        }

        return Boolean.FALSE;
    }

    /**
     * 管理方审核租客的订单
     *
     * @param bo 订单信息
     * @return 是否成功
     */
    @Override
    public Boolean audit(OrderBo bo) {
        if (bo.getId() == null) {
            throw new ServiceException("订单id不能为空！");
        }
        // 查询数据库中该订单信息
        Order order = baseMapper.selectById(bo.getId());
        if (BeanUtil.isEmpty(order)) {
            throw new ServiceException("订单不存在！");
        }
        if (!order.getPlatformAuditStatus().equals(AuditStatus.PENDING.getCode())) {
            throw new ServiceException("订单状态异常！");
        }

        if (bo.getPlatformAuditStatus().equals(AuditStatus.REJECTED.getCode())) {
            // TODO 平台审核-订单拒绝

            return baseMapper.updateById(MapstructUtils.convert(bo, Order.class)) > 0;
        }
        // 更新订单信息
        bo.setSigningStatus(SigningStatus.SIGNING.getCode()); // order签约中
        bo.setOrderStatus(OrderStatus.SIGNING.getCode()); // order总状态签约中
        return baseMapper.updateById(MapstructUtils.convert(bo, Order.class)) > 0;
    }

    /**
     * 管理方指定订单给资方用户
     *
     * @param bo 订单信息
     * @return
     */
    @Override
    public Boolean assign(OrderBo bo) {
        if (bo.getId() == null) {
            throw new ServiceException("订单id不能为空！");
        }
        if (bo.getCapitalUserId() == null) {
            throw new ServiceException("资方用户id不能为空！");
        }
        Order order = baseMapper.selectById(bo.getId());
        if (BeanUtil.isEmpty(order)) {
            throw new ServiceException("订单不存在！");
        }
        if (!order.getPlatformAuditStatus().equals(AuditStatus.APPROVED.getCode()) &&
            !order.getPlatformAuditStatus().equals(AuditStatus.REJECTED_REASSIGN.getCode())) {
            throw new ServiceException("订单状态未审核或未通过审核！");
        }
        if (order.getCapitalAuditStatus().equals(AuditStatus.APPROVED.getCode())) {
            throw new ServiceException("订单已有资方通过！");
        }
        order.setCapitalUserId(bo.getCapitalUserId());
        order.setCapitalAuditStatus(AuditStatus.PENDING.getCode());
        return baseMapper.updateById(order) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Order entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除订单信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 用户扫码后创建订单信息order
     *
     * @param house 房源信息
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createOrderByHouse(House house, Long userId, String userAuthUrl) {
        // 判断用户是否已经扫码创建订单
        if (baseMapper.selectCount(new LambdaQueryWrapper<Order>().eq(Order::getUserId, userId).eq(Order::getHouseId, house.getId())) > 0) {
            throw new ServiceException("用户已经扫码创建订单");
        }
        Order order = new Order();
        // 订单编号是年月日时分秒加上随机数
        order.setContractNo(DateUtils.dateTimeNow() + RandomUtil.randomNumbers(8));
        order.setStartDate(house.getStartDate());
        // 根据开始时间加上租期时间获取到期时间
        order.setEndDate(DateUtil.offsetMonth(house.getStartDate(), house.getLeaseTerm().intValue()));
        order.setContractMonth(house.getLeaseTerm());
        order.setRent(house.getRent());
        order.setDeposit(house.getDeposit());
        // 租金总额等于租金*订单时长
        order.setRentTotal(house.getRent().multiply(new BigDecimal(house.getLeaseTerm())));
        order.setHouseId(house.getId());
        order.setUserId(userId);
        order.setLessorUserId(house.getLessorId());
        order.setUserAuthUrl(userAuthUrl);
        // 资方id资方操作后添加
        order.setRemarks(house.getRemark());
        order.setOrderStatus(OrderStatus.PENDING.getCode()); // 订单状态-待生效
//        order.setSigningStatus(SigningStatus.SIGNING.getCode()); // 签约状态-签约中
        order.setPlatformAuditStatus(AuditStatus.PENDING.getCode()); // 平台审核状态-待审核
        order.setCapitalAuditStatus(AuditStatus.PENDING.getCode()); // 资方审核状态-待审核
        order.setPledgeStatus(PledgeStatus.PENDING_PAY.getCode()); // 押金状态-待支付
        order.setRentBillStatus(BillStatus.PENDING_PAY.getCode()); // 租金分期账单状态-待支付
//        order.setAdvanceBillStatus(BillStatus.PENDING_PAY.getCode()); // 垫资分期账单状态-待支付
        boolean b = baseMapper.insert(order) > 0;
        if (b) {
            house.setId(order.getId());
            // 创建订单信息成功 创建租金账单信息表hr_contract_bill
            // 首先创建押金账单
            contractBillService.createDepositBill(order);
            // 创建租金账单
            contractBillService.createRentBill(order);
        }
        return b;
    }

    /**
     * 根据houseId查询订单(房源是否未出租)
     *
     * @param houseId 房源id
     * @return Boolean true:未出租，false:已经出租
     */
    @Override
    public Boolean queryByHouseId(Long houseId) {
        LambdaQueryWrapper<Order> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Order::getHouseId, houseId);
        // 订单状态不是已结束
//        lqw.ne(Order::getOrderStatus, OrderStatus.ENDED.getCode());
        List<Order> orderList = baseMapper.selectList(lqw);
        // 订单列表不为空，则说明该房屋正在被出租状态
        if (CollUtil.isNotEmpty(orderList)) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 根据合同编号查询订单信息
     *
     * @param contractNo 合同编号
     * @return 订单信息
     */
    @Override
    public OrderVo queryOrderByContractCode(String contractNo) {
        if (StrUtil.isBlank(contractNo)) {
            throw new ServiceException("合同编号不能为空！");
        }
        Long userId = LoginHelper.getUserId();
        OrderVo orderVo = baseMapper.selectVoOne(new LambdaQueryWrapper<Order>().eq(Order::getContractNo, contractNo).eq(Order::getUserId, userId));
        if (BeanUtil.isEmpty(orderVo)) {
            throw new ServiceException("根据合同编号查询订单信息不存在！");
        }
        return orderVo;
    }
}
